using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

namespace ScottLane.VideoInbox
{
    /// <summary>
    /// Contains the information required to download a video.
    /// </summary>
    public class DownloadManifest
    {
        #region Constructors

        /// <summary>
        /// Parameterless constructor for serialization purposes.
        /// </summary>
        private DownloadManifest()
        {
            _downloads = new List<Download>();
        }

        /// <summary>
        /// Initializes a new instance of the DownloadManifest class for a media file with the
        /// specified file name.
        /// </summary>
        /// <param name="mediaFileName">The video or playlist file name.</param>
        private DownloadManifest(string mediaFileName)
            : this()
        {
            _mediaFileName = mediaFileName;
        }

        #endregion

        #region Properties

        private string _mediaFileName;

        /// <summary>
        /// Gets the media file name.
        /// </summary>
        public string MediaFileName
        {
            get { return _mediaFileName; }
            set { _mediaFileName = value; }
        }

        /// <summary>
        /// Gets the manifest file name.
        /// </summary>
        public string FileName
        {
            get { return GetFileName(_mediaFileName); }
        }

        private string _title;

        /// <summary>
        /// Gets or sets the manifest title.
        /// </summary>
        public string Title
        {
            get { return _title; }
            set { _title = value; }
        }

        private List<Download> _downloads;

        /// <summary>
        /// Gets the files to be downloaded.
        /// </summary>
        public List<Download> Downloads
        {
            get { return _downloads; }
            set { _downloads = value; }
        }

        /// <summary>
        /// Gets a value indicating whether the manifest file exists.
        /// </summary>
        public bool Exists
        {
            get { return File.Exists(FileName); }
        }

        #endregion

        /// <summary>
        /// Creates the manifest file.
        /// </summary>
        public void Create()
        {
            Delete();

            FileInfo manifestFile = new FileInfo(FileName);
            XmlSerializer serializer = new XmlSerializer(this.GetType());
            FileStream stream = manifestFile.OpenWrite();
            serializer.Serialize(stream, this);
            stream.Close();

            manifestFile.Refresh();
            //manifestFile.CreationTime = video.Created;
            manifestFile.Attributes = FileAttributes.Hidden;
        }

        /// <summary>
        /// Deletes the manifest file.
        /// </summary>
        public void Delete()
        {
            File.Delete(FileName);
        }

        /// <summary>
        /// Loads a manifest file from disk.
        /// </summary>
        /// <param name="fileName">The manifest file name.</param>
        /// <returns>The manifest instance.</returns>
        public static DownloadManifest Load(string fileName)
        {
            DownloadManifest manifest;
            FileInfo manifestFile = new FileInfo(fileName);

            if (manifestFile.Exists)
            {
                XmlSerializer serializer = new XmlSerializer(typeof(DownloadManifest));
                FileStream stream = manifestFile.OpenRead();
                manifest = (DownloadManifest)serializer.Deserialize(stream);
                stream.Close();
            }
            else
            {
                throw new ArgumentException("The manifest file does not exist", "fileName");
            }

            return manifest;
        }


        /// <summary>
        /// Creates a manifest file instance with all required information to download a video.
        /// </summary>
        /// <param name="video">The video.</param>
        /// <returns>The manifest.</returns>
        public static DownloadManifest FromVideo(DownloadableVideo video)
        {
            DownloadManifest manifest = new DownloadManifest(video.DownloadFileName);
            manifest.Title = video.Title;

            Download download = new Download();
            download.SourceUrl = video.SourceLocationString;
            download.DestinationFileName = video.DownloadFileName;
            download.Shortcuts = video.Shortcuts;
            manifest.Downloads.Add(download);

            return manifest;
        }

        /// <summary>
        /// Gets the manifest file for a playlist.
        /// </summary>
        /// <param name="playlistFileName">The playlist file name.</param>
        /// <returns></returns>
        public static DownloadManifest FromPlaylist(Playlist playlist)
        {
            DownloadManifest manifest = new DownloadManifest(playlist.FileName);
            manifest.Title = playlist.Title;

            foreach (Video video in playlist.Videos)
            {
                //manifest.Downloads.Add(new Download(video.SourceLocationString, video.DownloadFileName));
            }

            return manifest;
        }

        /// <summary>
        /// Gets the manifest file name from the specified media file name.
        /// </summary>
        /// <param name="mediaFileName">The media file name.</param>
        /// <returns>The manifest file name.</returns>
        public static string GetFileName(string mediaFileName)
        {
            return Path.ChangeExtension(mediaFileName, ".xml");
        }
    }
}
